package com.phoenix.jsef.common;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 数据转换工具类
 * 
 * @author 李启联
 *
 */
public class ConvertUtils {


    /**
     * 把Map对象中的内容填充到指定实体对象中，<em>支持递归<em/>
     * 填充规则：[实体属性名称与源Map对象字段 	  1.不分大小写  2.驼峰格式相互可以转成 相对应],找到便填充。
     * @param map 源Map对象数据
     * @param type 目标实体对象的类型（如：T.class）
     * @return 填充好的实体对象
     * @throws Exception
     */
    public static <T> T dataMapToObject(Map<String, Object> map, Class<T> type) throws Exception {
        if (null == map || map.isEmpty())
            return null;
        T entity = (T) Class.forName(type.getName()).newInstance();
        String fieldName = "";
        Object obj =null,val=null;
        Class elementType = null;
        Field[] fields = Class.forName(type.getName()).getDeclaredFields();
        for (Field field : fields) { // 遍历所有属性
            fieldName = field.getName(); // 获取属性的名字

            field.setAccessible(true);

            if(ReflectionUtils.isStaticFinalField(field))//如果该字段使用了static final 修饰 【通常这么修饰的字段是用来定义常量的】
                continue;//	遍历下一个

            obj = CUtils.getValueFromMapByLikeKey(fieldName, map);//平行查找与属性名相同键的Map对应的值

            if (field.getType().isAssignableFrom(List.class)) { // 如果属性是另外类型实体的泛型List集合
                if (null != obj) {
                    if (obj instanceof List || obj.getClass().isAssignableFrom(List.class)){
                        List collection = new ArrayList();
                        elementType = ReflectionUtils.getFieldClass(field);// 得到List泛型参数类型
                        for(Map<String, Object> subMap : (List<Map<String, Object>>)obj) {
                            collection.add(dataMapToObject(subMap,elementType));
                        }
                        field.set(entity,collection);
                    }
                }
            }
            else if(null != obj && obj.getClass().isAssignableFrom(Map.class)){//如果属性是另外类型的单个实体
                field.set(entity,dataMapToObject((Map<String, Object>)obj,field.getType()));
            }
            else {// 如果属性类型是 'string','Date','int', 'long','Double'......
                if (null != obj && obj.toString().length() > 0) {
                    val = convertObjectToTargetType(obj, field.getType());
                    field.set(entity, val);
                }
            }

        }

        return entity;
    }

    /**
     * 把List<Map>对象中的内容填充到指定实体对象集合中，<em>支持递归<em/>
     * @param mapList 源List<Map>对象数据
     * @param type 目标实体对象的类型（如：T.class）
     * @return 填充好的实体对象集合
     * @throws Exception
     */
    public static <T> List<T> dataMapListToObjects(List<Map<String, Object>> mapList, Class<T> type) throws Exception {
        List collection = new ArrayList();
        for(Map<String, Object> map : mapList) {
            collection.add(dataMapToObject(map,type));
        }
        return collection;
    }

	/**
	 * 将指定的对象转换为对应类型的对象
	 * 
	 * @param object
	 *            要转换的对象
	 * @param type
	 *            对应类型 如：Integer.class Date.class 等
	 * @return
	 */
	public static Object convertObjectToTargetType(Object object, Class<?> type) {
        if (type == String.class) {
            return object.toString();
        } else if (type == int.class || type == Integer.class) {
            if (object instanceof Number) {
                Number number = (Number) object;
                return number.intValue();
            } else
                return Integer.parseInt(object.toString());
        } else if (type == byte.class || type == Byte.class) {
            if (object instanceof Number) {
                Number number = (Number) object;
                return number.byteValue();
            } else
                return Byte.parseByte(object.toString());
        } else if (type == short.class || type == Short.class) {
            if (object instanceof Number) {
                Number number = (Number) object;
                return number.shortValue();
            } else
                return Short.parseShort(object.toString());
        } else if (type == long.class || type == Long.class) {
            if (object instanceof Number) {
                Number number = (Number) object;
                return number.longValue();
            } else
                return Long.parseLong(object.toString());
        } else if (type == float.class || type == Float.class) {
            if (object instanceof Number) {
                Number number = (Number) object;
                return number.floatValue();
            } else
                return Float.parseFloat(object.toString());
        } else if (type == double.class || type == Double.class) {
            if (object instanceof Number) {
                Number number = (Number) object;
                return number.doubleValue();
            } else
                return Double.parseDouble(object.toString());
        } else if (type == boolean.class || type == Boolean.class) {
            return Boolean.valueOf(object.toString());
        } else if (type == Date.class) {
            return DateUtils.parse(object.toString(), DateUtils.FORMAT_FULL);
        }else if(type == BigDecimal.class )
            return new BigDecimal(object.toString());
        else if(type == Timestamp.class){
            if (object instanceof Number) {
                Number number = (Number) object;
                return new Timestamp((number.longValue()));
            } else{
                return new Timestamp(DateUtils.parse(object.toString(), DateUtils.FORMAT_FULL).getTime());
            }
        }

        return object;

	}
}
